/*
 * This file is part of ELCube.
 *
 * ELCube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ELCube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ELCube.  If not, see <https://www.gnu.org/licenses/>.
 */
package cn.nkpro.elcube.components.financial.cards

import cn.nkpro.elcube.annotation.NkNote
import cn.nkpro.elcube.co.easy.EasyCollection
import cn.nkpro.elcube.co.easy.EasyEntity
import cn.nkpro.elcube.co.easy.EasySingle
import cn.nkpro.elcube.co.spel.NkSpELManager
import cn.nkpro.elcube.docengine.NkAbstractCard
import cn.nkpro.elcube.docengine.NkDocEngine
import cn.nkpro.elcube.docengine.model.DocDefIV
import cn.nkpro.elcube.docengine.model.DocHV
import cn.nkpro.elcube.utils.DateTimeUtilz
import cn.nkpro.elcube.utils.MathUtils
import org.dom4j.Document
import org.dom4j.DocumentHelper
import org.dom4j.Element
import org.dom4j.io.OutputFormat
import org.dom4j.io.XMLWriter
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.annotation.Order
import org.springframework.expression.EvaluationContext
import org.springframework.stereotype.Component

// todo 待开发卡片
@Order(100016)
@NkNote("财务应收账款")
@Component("NkCardAccountingReceivable")
class NkCardAccountingReceivable extends NkAbstractCard<List<Item>,Def> {

    @Autowired
    private NkDocEngine docEngine
    @Autowired
    private NkSpELManager spELManager

    @Override
    List<Item> calculate(DocHV doc, List<Item> data, DocDefIV defIV, Def d, boolean isTrigger, Object options) {

        List<Item> receivables = new ArrayList<>()
        if(doc.preDocId){
            def prev = docEngine.detail(doc.preDocId)
            def context = spELManager.createContext(prev)
            def startDate = spELManager.invoke("data.scheme?.startDate",context) as Long
            def bills = spELManager.invoke("data.bills?.?[billType=='利息']",context) as List

            Calendar calendar = Calendar.getInstance()
            calendar.setTimeInMillis(startDate * 1000)

            bills.forEach{bill->
                def each = EasySingle.from(bill)
                // 到期日期
                def billType   = each.get("billType") as String
                // 到期日期
                def expireDate = each.get("expireDate") as Long
                // 账单金额
                def amount     = each.get("amount") as Double
                // 期间日数
                def dateDiff   = DateTimeUtilz.dateDiff(expireDate, startDate)
                // 期间日金额
                def dayAmount  = MathUtils.currencyValue(amount / dateDiff)

                while(calendar.getTimeInMillis()/1000 < expireDate){

                    calendar.add(Calendar.DAY_OF_MONTH,1)

                    Item item = new Item()
                    // 账单类型
                    item.type = billType
                    // 应记账日期
                    item.date = (Long) (calendar.getTimeInMillis() / 1000)
                    // 应记账金额，最后一日取余额
                    item.amount = item.date == expireDate ? amount : dayAmount

                    amount -= dayAmount

                    //def exists = data.find {i.date==item.date}
                    //if(exists){
                    //    item.accountingAmount = exists.accountingAmount
                    //}

                    receivables.add(item)
                }

                // 记录上一期到期日为下一期的开始日期
                startDate = expireDate
            }
        }

        data = receivables

        return super.calculate(doc, data, defIV, d, isTrigger, options) as List<Item>
    }

    static class Item implements Serializable{
        Long date
        String type
        Double amount
        Double accountingAmount
    }

    static class Def implements Serializable{
        String conditionSpEL
        List<HeadDef> heads
        List<DetailDef> details
    }
    static class HeadDef implements Serializable{
        String key
        String valueSpEL
        String desc

    }
    static class DetailDef implements Serializable{
        String pk_accasoa
        String pk_currtype
        String category
        String dataSourceSpEL
        String amountSpEL
        String explanation
        List<DetailAssDef> asses
    }
    static class DetailAssDef implements Serializable{
        String pk_Checktype
        String pk_CheckvalueSpEL
    }
}
